home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * NNTP Client - See RFC977
- * Jeffrey R. Comstock. - NR0D - Bloomington, Minnesota USA
- * Copyright 1990 Jeffrey R. Comstock, All Rights Reserved.
- * Permission granted for non-commercial copying and use, provided
- * this notice is retained.
- *
- * DB3FL 9107xx: heavily rewritten and bug fixing in file-handling
- * DB3FL 920121: splitted into several files
- * DB3FL 920131: included IHAVE command/offer to server
- * DG1ZX 9210xx: minimizing overhead in ihave cmd and bug fixing
- * DG1ZX 9303xx: included POST and XDHR command
- * DG1ZX 930728: included nntp restrictions and history lifetime
- *
- */
-
- #include <stdio.h>
- #include <dos.h>
- #include <time.h>
- #include <ctype.h>
- #include <dir.h>
- #include <io.h>
-
- #include "global.h"
- #include "config.h"
- #include "nntp.h"
- #include "files.h"
- #include "domain.h"
- #include "socket.h"
- #include "cmdparse.h"
- #include "session.h"
- #ifdef LZW
- #include "lzw.h"
- #endif
-
- char msgid[] = "Message-Id: ";
- char subj[] = "Subject: ";
- char ngrps[] = "Newsgroups: ";
- char frm[] = "From: ";
- char ndate[] = "Date: ";
- static char reply_to[] = "Reply-To: ";
- char pth[] = "Path: ";
- static char quitcmd[] = "QUIT\n";
-
- static struct post Post;
- static struct Servers *Nntpserver = NULLSERVER;
-
- static int16 NnIhave = 0;
-
- #ifdef NNTPRESTRICT
- int restrict = 0;
- #endif
-
- #ifdef NNTPLIFETIME
- int16 lifetime = 180; /* default: 180 days */
- #endif
-
-
-
- /* handles the response code of an incoming msg
- * returncode: -1 error; 0 no code; value of response code on success */
- static int near
- getreply(struct nntpsv *cb)
- {
- int response;
- char *cp;
-
- while(recvline(cb->s,cb->buf,LineLen) != -1) {
- /* skip informative messages and blank lines */
- if(*cb->buf == '\0' || *cb->buf == '1')
- continue;
- if((cp = strchr(cb->buf,' ')) != NULLCHAR) {
- *cp = '\0';
- response = atoi(cb->buf);
- *cp = ' ';
- }
- else {
- response = 500;
- }
- return (response < 500) ? response : -1;
- }
- return -1;
- }
-
- static char * near
- pollpos(char *line,char *name,FILE *f)
- {
- long t;
- char *cp;
-
- rewind(f);
- for(t = 0L; fgets(line,LineLen,f) != NULLCHAR; t = ftell(f)) {
- if((cp = strchr(line,' ')) == NULLCHAR)
- continue; /* something wrong with this line, skip it */
- *cp = '\0';
- if(strnicmp(line,name,strcspn(name," ")) == 0) {
- fseek(f,t,SEEK_SET);
- return cp+1;
- }
- }
- return 0L;
- }
-
- static void
- nntppoll(int unused, void *cb1, void *p)
- {
- char *cp, line[LINELEN], *firstpoll;
- struct sockaddr_in fsocket;
- struct nntpsv *cb;
- struct tm *ltm;
- FILE *f = NULLFILE, *f1 = NULLFILE, *pf;
- int err = 0, r, now, ret;
- int32 lastday, SavePollTime;
- struct Servers *sp = (struct Servers *)cb1;
-
- if (!Filecheck)
- if(check_system())
- return;
-
- if(availmem() < Memthresh) {
- start_timer(&sp->nntpt);
- return;
- }
- /* check connection window (in local time !) */
- ltm = localtime(&currtime);
- now = ltm->tm_hour * 100 + ltm->tm_min;
-
- if (sp->lowtime < sp->hightime) {
- /* doesn't cross midnight */
- if (now < sp->lowtime || now >= sp->hightime) {
- start_timer(&sp->nntpt);
- return;
- }
- } else {
- if (now < sp->lowtime && now >= sp->hightime) {
- start_timer(&sp->nntpt);
- return;
- }
- }
-
- /* save connection time to update pollfile (DG1ZX) */
- SavePollTime = currtime;
-
- if((pf = open_file(Poll,"r+",0,1)) == NULLFILE ||
- (cb = (struct nntpsv *)mxallocw(sizeof(struct nntpsv))) == NULLNNTPSV) {
- start_timer(&sp->nntpt);
- return;
- }
- stop_timer(&sp->nntpt);
-
- /* if no entry for host in poll-file exist, set date
- to yesterday (DG1ZX) */
-
- if((cp = pollpos(line,sp->name,pf)) == NULLCHAR) {
- lastday = currtime - 1*DAYS;
- ltm = gmtime(&lastday);
- sprintf(firstpoll,"%02d%02d%02d %02d%02d%02d",
- ltm->tm_year,ltm->tm_mon + 1,ltm->tm_mday,
- ltm->tm_hour,ltm->tm_min,ltm->tm_sec);
- cb->newnews = strxdup(firstpoll);
- } else {
- rip2(cp);
- cb->newnews = strxdup(cp);
- }
- fclose(pf);
-
- fsocket.sin_family = AF_INET;
- fsocket.sin_addr.s_addr = cb->dest = sp->dest;
- fsocket.sin_port = IPPORT_NNTP;
-
- if((cb->s = socket(AF_INET,SOCK_STREAM,0)) == -1)
- goto quit;
-
- sockmode(cb->s,SOCK_ASCII);
-
- if(connect(cb->s,(char *)&fsocket,SOCKSIZE) == -1)
- goto quit;
-
- log(cb->s,"NNTP Connect");
-
- if(getreply(cb) == -1) /* throw away any hello msg */
- goto quit;
-
- #ifdef LZW
- if (LzwActive) {
- usprintf(cb->s,"XLZW %d %d\n",Lzwbits,Lzwmode);
- if((ret = getreply(cb)) == 235) { /* eat negative response */
- lzwinit(cb->s,Lzwbits,Lzwmode);
- }
- }
- #endif
-
- usputs(cb->s,"SLAVE\n");
- if(getreply(cb) != 202)
- goto quit;
- if((f = temp_file(0,1)) == NULLFILE)
- goto quit;
-
- cb->slave = 1;
-
- usprintf(cb->s,"NEWNEWS %s %s GMT\n",sp->newsgroups,cb->newnews);
-
- if(getreply(cb) != 230)
- goto quit1;
- if(recv_file(f,cb->s) == -1)
- goto quit1;
- if((f1 = temp_file(cb->s,1)) == NULLFILE)
- goto quit1;
-
- rewind(f);
-
- while(fgets(cb->buf,LineLen,f),!feof(f)) {
- rip2(cb->buf);
- if (strcmp(cb->buf,".") == 0)
- break;
- if (check_article(cb->buf) == 1)
- continue;
- usprintf(cb->s,"ARTICLE %s\n",cb->buf);
- for (;;) {
- if ((r = recvline(cb->s,cb->buf,LineLen)) == -1)
- break;
- rip2(cb->buf);
- if(!isdigit(cb->buf[0])) {
- r = -1;
- continue;
- } else {
- r = atoi(cb->buf);
- break;
- }
- }
- if(r == -1) {
- fclose(f1);
- goto quit1;
- }
- if (r == 220) {
- if (recv_file(f1,cb->s) == -1) {
- fclose(f1);
- goto quit1;
- }
- rewind(f1);
- while(fgets(cb->buf,LineLen,f1),!feof(f1)) {
- rip2(cb->buf);
- if (strnicmp(cb->buf,msgid,12) == 0) {
- cp = strchr(cb->buf,' ');
- cb->id = strxdup((*++cp < 32) ? "(none)" : cp);
- break;
- }
- }
- /* minimum header in article required !
- Now check again, if same news exists in history
- (DG1ZX) */
- if (garbled(f1) == 0 && check_article(cb->id) == 0) {
- rewind(f1);
- xfer_article2(f1,cb);
- }
- }
- fclose(f1);
- if ((f1 = temp_file(cb->s,1)) == NULLFILE)
- goto quit1;
- }
- fclose(f1);
-
-
- /* IHAVE offer */
-
- if(NnIhave && (f1 = tmpfile()) != NULLFILE) {
- sprintf(line,"%s %s",NnIhave == 2 ? "*" : sp->newsgroups,cb->newnews);
- #if (defined(NNTPRESTRICT) || defined(NNTPLIFETIME))
- if(newnews(line,cb,f1,0) < 1) {
- #else
- if(newnews(line,cb,f1) < 1) {
- #endif
- fclose(f1);
- }
- else {
- rewind(f1);
- while(fgets(line,sizeof(line),f1),!feof(f1)) {
- /* check if MID exist at the other host (dg1zx) */
- if (check_ihave (f,line,cb,sp->name))
- continue;
- usprintf(cb->s,"IHAVE %s",line);
- if((ret = getreply(cb)) == -1) {
- err = 1;
- break;
- }
- if(ret != 335)
- continue;
- rip2(line);
- if(doarticle(line,cb,0,NULLCHAR) < 1) {
- usputs(cb->s,NEol);
- if((ret = getreply(cb)) == -1) {
- err = 1;
- break;
- }
- continue;
- }
- if((ret = getreply(cb)) != 235)
- continue;
- }
- fclose(f1);
- }
- }
-
- /*
- * update pollfile
- * Now write back the opening date and time.
- * Time in poll and history files are always GMT (DG1ZX)
- */
-
- if(!err && (pf = fopen(Poll,"r+")) != NULLFILE) {
- pollpos(line,sp->name,pf);
- ltm = gmtime(&SavePollTime);
- fprintf(pf,"%s %02d%02d%02d %02d%02d%02d\n",
- sp->name,
- ltm->tm_year,ltm->tm_mon + 1,ltm->tm_mday,
- ltm->tm_hour,ltm->tm_min,ltm->tm_sec);
- fclose(pf);
- }
-
- quit1:
- fclose(f);
- quit:
- usprintf(cb->s,quitcmd);
- if(getreply(cb) == -1) ;
- close_s(cb->s);
- xfree(cb->newnews);
- xfree((char *)cb);
- start_timer(&sp->nntpt);
- }
-
- static void
- poll(void *p)
- {
- newproc("NNTP Client", 2048, nntppoll, 0, p, NULL, 0);
- }
-
- static char * near
- input_line(char *msg,struct session *sp)
- {
- static char buf[LineLen];
-
- for (;;) {
- usputs(sp->output,msg);
- usflush(sp->output);
- if(recvline(sp->input,buf,LineLen) == -1)
- return NULLCHAR;
- rip2(buf);
- if(!check_blank(buf)) {
- return buf;
- }
- }
- }
-
-
-
- /* ---------------------- NNTP Client subcmds ----------------------- */
-
- /* lists active newsgroups
- * returncode: -1 if error; 0 success */
- static int
- donnactive(int argc,char *argv[],void *p)
- {
- FILE *fp;
- char line[80], *cp;
-
- if((fp = open_file(Active,READ_TEXT,0,1)) == NULLFILE)
- return -1;
-
- tputs("last first post newsgroup\n");
-
- while(fgets(line,sizeof(line),fp),!feof(fp)) {
- if((cp = strchr(line,' ')) != NULLCHAR) {
- *cp = '\0';
- rip2(++cp);
- tprintf("%s %s\n",cp,line);
- }
- }
- fclose(fp);
- return 0;
- }
-
- /* add nntp servers to list */
- static int
- donnadds(int argc,char *argv[],void *p)
- {
- struct Servers *np;
- int32 addr;
-
- if((addr = resolve(argv[1])) == 0) {
- tprintf(Badhost,argv[1]);
- return -1;
- }
- for(np = Nntpserver; np != NULLSERVER; np = np->next)
- if(np->dest == addr)
- break;
- if (np == NULLSERVER) {
- np = (struct Servers *)mxallocw(sizeof(struct Servers));
- np->dest = addr;
- np->name = strxdup(argv[1]);
- np->next = Nntpserver;
- Nntpserver = np;
- np->newsgroups = NULLCHAR;
- np->lowtime = np->hightime = -1;
- np->nntpt.func = poll; /* what to call on timeout */
- np->nntpt.arg = (void *)np;
- }
- if (argc > 3) {
- int i;
- if (np->newsgroups == NULLCHAR) {
- np->newsgroups = mxallocw(LineLen);
- *np->newsgroups = '\0';
- }
- for (i = 3; i < argc; ++i) {
- if (isdigit(*argv[i])) {
- char *cp, *cp1;
-
- cp = argv[i];
-
- if(((char *)((cp1 = strchr(cp,':')) != NULLCHAR)
- != strrchr(cp,':') && strchr(cp,'-'))) {
- /* there must be 2 different ':' and 1 '-' */
- *cp1 = 0;
- np->lowtime = atoi(cp) * 100;
- cp = ++cp1;
- while(*++cp != '-') ;
- *cp = '\0';
- np->lowtime += atoi(cp1);
- cp1 = ++cp;
- while(*++cp1 != ':') ;
- *cp1 = 0;
- np->hightime = atoi(cp) * 100 + atoi(++cp1);
- }
- } else if ((strlen(np->newsgroups)+strlen(argv[i])+2) >= LineLen)
- tprintf("To many groups, '%s' ignored\n", argv[i]);
- else { /* it's a group, and it fits... add it to list */
- if (*np->newsgroups != '\0')
- strcat(np->newsgroups, ",");
- strcat(np->newsgroups, argv[i]);
- }
- }
- if (*np->newsgroups == '\0') { /* No groups specified? */
- xfree(np->newsgroups);
- np->newsgroups = NULLCHAR;
- }
- }
- /* set timer duration */
- set_timer(&np->nntpt,atol(argv[2]) * 1000L);
- start_timer(&np->nntpt); /* and fire it up */
- return 0;
- }
-
- /* drops nntp servers from list */
- static int
- donndrops(int argc,char *argv[],void *p)
- {
- struct Servers *np, *npprev = NULLSERVER;
- int32 addr;
-
- if((addr = resolve(argv[1])) == 0) {
- tprintf(Badhost,argv[1]);
- } else {
- for(np = Nntpserver; np != NULLSERVER; npprev = np, np = np->next)
- if(np->dest == addr) {
- stop_timer(&np->nntpt);
- xfree(np->name);
- if (np->newsgroups)
- xfree(np->newsgroups);
- if(npprev != NULLSERVER)
- npprev->next = np->next;
- else
- Nntpserver = np->next;
- xfree((char *)np);
- return 0;
- }
- }
- return -1;
- }
-
- /* copies a news from given newsgroup to the mailbox */
- static int
- donndump(int argc,char *argv[],void *p)
- {
- FILE *t, *f, *o;
- struct article *art;
- char line[LineLen], newsname[10], *cp;
- struct ffblk blk;
-
- if((art = (struct article *)mxallocw(sizeof(struct article))) == NULLARTICLE)
- return -1;
-
- art->group = strxdup(argv[1]);
-
- if(get_path2(art) < 1)
- goto error;
-
- rip2(art->path);
- sprintf(line,"%s/*.*",art->path);
-
- if(findfirst(line,&blk,0)) {
- tputs("No news in newsgroup\n");
- goto error;
- }
-
- sprintf(newsname,"%.8s",argv[2]);
- sprintf(line,"%s/%s.txt",Mailspool,newsname);
-
- if ((o = open_file(line,"a+",0,1)) == NULLFILE)
- goto error;
- if(!(mlock(Mailspool,newsname))) {
- tprintf("Newsgroup dump to %s\n",line);
- for (;;) {
- if((t = temp_file(0,1)) == NULLFILE) {
- fclose(o);
- goto error;
- }
- sprintf(line,"%s/%s",art->path,blk.ff_name);
- /* Open the article */
- if ((f = open_file(line,READ_TEXT,0,1)) == NULLFILE) {
- fclose(t);
- fclose(o);
- goto error;
- }
- pwait(NULL);
- tputc('.'); /* One article/dot processed */
- tflush();
-
- while(fgets(line,LineLen,f),!feof(f)) {
- fputs(line,t);
- if (!strnicmp(line,frm,6)) {
- cp = strchr(line,' ') + 1;
- fprintf(o,"From %s",cp);
- }
- }
- rewind(t);
- while(fgets(line,LineLen,t),!feof(t))
- fputs(line,o);
-
- fputc('\n',o);
- fclose(t);
- fclose(f);
- if (findnext(&blk))
- break;
- }
- rmlock(Mailspool,newsname);
- } else
- tputs("Mailfile is busy, try later");
-
- fclose(o);
- tputs("\n");
-
- error:
- xfree(art->path);
- xfree(art->group);
- xfree(art);
- return 0;
- }
-
- static int
- donnfull(int argc,char *argv[],void *p)
- {
- if(argc < 2 && Post.fullname != NULLCHAR)
- tprintf("%s\n",Post.fullname);
- else {
- xfree(Post.fullname);
- Post.fullname = strxdup(argv[1]);
- }
- return 0;
- }
-
- static int
- donnhost(int argc,char *argv[],void *p)
- {
- if(argc < 2 && Host != NULLCHAR)
- tprintf("%s\n",Host);
- else {
- xfree(Host);
- Host = strxdup(argv[1]);
- }
- return 0;
- }
-
- static int
- donnihave(int argc,char *argv[],void *p)
- {
- return setintrc(&NnIhave,"NNTP Ihave",argc,argv,0,2);
- }
-
- static int
- donnkick(int argc,char *argv[],void *p)
- {
- int32 addr;
-
- if((addr = resolve(argv[1])) == 0) {
- tprintf(Badhost,argv[1]);
- } else {
- struct Servers *np;
-
- for(np = Nntpserver; np != NULLSERVER; np = np->next) {
- if(np->dest == addr) {
- /* If the timer is running,
- * the timeout function can be called
- */
- if(run_timer(&np->nntpt) || dur_timer(&np->nntpt) == 0) {
- stop_timer(&np->nntpt);
- poll((void *)np);
- }
- return 0;
- }
- }
- tputs("No such server\n");
- }
- return 0;
- }
-
- #ifdef LZW
- /* sets LzwActive flag */
- static int
- donnlzw(int argc,char *argv[],void *p)
- {
- return setbool(&LzwActive,"NNTP LZW",argc,argv);
- }
- #endif
-
- /* list nntp servers */
- static int
- donnlists(int argc,char *argv[],void *p)
- {
- struct Servers *np;
- char tbuf[80];
-
- for(np = Nntpserver; np != NULLSERVER; np = np->next) {
- if (np->lowtime != -1 && np->hightime != -1)
- sprintf(tbuf, " -- %02d:%02d-%02d:%02d",
- np->lowtime/100, np->lowtime%100,
- np->hightime/100, np->hightime%100);
- else
- tbuf[0] = '\0';
- tprintf("%-32s (%lu/%lu%s)\n Groups: %s\n", np->name,
- read_timer(&np->nntpt) /1000L,
- dur_timer(&np->nntpt) /1000L,
- tbuf,
- np->newsgroups ? np->newsgroups : "");
- }
- return 0;
- }
-
- static int
- donnmaxcli(int argc,char *argv[],void *p)
- {
- extern unsigned short Nntpmaxcli;
-
- return setshort(&Nntpmaxcli,"NNTP maxcli",argc,argv);
- }
-
- static int
- donnorgan(int argc,char *argv[],void *p)
- {
- if(argc < 2 && Post.organ != NULLCHAR)
- tprintf("%s\n",Post.organ);
- else {
- xfree(Post.organ);
- Post.organ = strxdup(argv[1]);
- }
- return 0;
- }
-
- /* manually entering new news
- * returncode: -1 if error; 0 success */
- static int
- donnpost(int argc,char *argv[],void *p)
- {
- struct session *sp;
- struct nntpsv *mp;
- char buf[LineLen], *cp;
- long id;
- FILE *f, *idf, *ufp;
-
- if (!Filecheck)
- if(check_system())
- return -1;
-
- if((sp = newsession("NNTP Post",MORE,0,1)) == NULLSESSION) {
- tputs(Nosess);
- return -1;
- }
- if((mp = (struct nntpsv *)mxallocw(sizeof(struct nntpsv))) == NULLNNTPSV)
- return -1;
-
- for (;;) {
- if ((f = temp_file(0,1)) == NULLFILE)
- goto done;
-
- if (Post.user == NULLCHAR)
- Post.user = strxdup(input_line("User name? ",sp));
- fprintf(f,"%s%s\n",pth,Post.user);
- fprintf(f,"%s%s@%s",frm,Post.user,Hostname);
-
- if (Post.fullname == NULLCHAR)
- Post.fullname = strxdup(input_line("Fullname? ",sp));
- fprintf(f," (%s)\n",Post.fullname);
-
- fprintf(f,"%s%s\n",ngrps,input_line("Newsgroup? ",sp));
- fprintf(f,"%s%s\n",subj,input_line("Subject? ",sp));
-
- id = get_msgid();
- fprintf(f,"%s<%ld@%s>\n",msgid,id,Hostname);
- fprintf(f,"Date: %s",ptime(&currtime));
- fprintf(f,"Sender: NNTP@%s\n",Hostname);
-
- if (Post.reply != NULLCHAR)
- fprintf(f,"%s%s\n",reply_to,Post.reply);
-
- if (Post.organ != NULLCHAR)
- fprintf(f,"Organization: %s\n",Post.organ);
-
- fputc('\n',f);
- tputs("Enter message - end with .\n");
-
- for (;;) {
- if(recvline(sp->input,buf,LineLen) == -1)
- break;
- if(strcmp(buf,".u\n") == 0
- || strcmp(buf,".r\n") == 0) {
- tputs("Filename? ");
- recvline(sp->input,buf,LineLen);
- rip2(buf);
- if(*buf != '\0'
- && (ufp = open_file(buf,READ_TEXT,0,1)) != NULLFILE) {
- while(fgets(buf,LineLen,ufp),!feof(ufp))
- fputs(buf,f);
- fclose(ufp);
- }
- tputs("(continue)\n");
- }
- if(strcmp(buf,".\n") == 0
- || strcmpi(buf,"***END\n") == 0
- || strcmpi(buf,"/EX\n") == 0)
- break;
- fputs(buf,f);
- }
- if (Post.sig != NULLCHAR) {
- if ((idf = fopen(Post.sig,READ_TEXT)) != NULLFILE ) {
- while(fgets(buf,LineLen,idf),!feof(idf))
- fputs(buf,f);
- fclose(idf);
- tputs("(Sig-file appended)\n");
- }
- }
- tputc('\n');
-
- loop: cp = input_line("[Send, Abort, Exit, List] ",sp);
- switch(tolower(*cp)) {
- case 's':
- rewind(f);
- sprintf(mp->buf,"<%ld@%s>",id,Hostname);
- mp->id = strxdup(mp->buf);
- xfer_article2(f,mp);
- break;
- case 'l':
- rewind(f);
- while(fgets(buf,LineLen,f),!feof(f))
- tputs(buf);
- rewind(f);
- goto loop;
- case 'e':
- fclose(f);
- goto done;
- case 'a':
- break;
- default:
- goto loop;
- }
- fclose(f);
- cp = input_line("Post another? (y/n) ",sp);
- if(tolower(*cp) == 'n')
- goto done;
- }
-
- done:
- keywait(NULLCHAR,1);
- xfree((char *) mp);
- freesession(sp);
- return 0;
- }
-
- static int
- donnquiet(int argc,char *argv[],void *p)
- {
- return setintrc(&Nntpquiet,"NNTP quiet",argc,argv,0,3);
- }
-
- static int
- donnread(int argc,char *argv[],void *p)
- {
- FILE *f;
- struct session *sp;
- struct article *art;
- char cp[LINELEN], buf[81];
- int number, row, flag = argc;
-
- if((art = (struct article *)mxallocw(sizeof(struct article))) == NULLARTICLE)
- return -1;
-
- art->group = strxdup(argv[1]);
- if(get_path2(art) == 1) {
- if(argc > 2) {
- number = atoi(argv[2]);
- } else
- number = 1;
-
- sprintf(cp,"%s/news.rc",art->path);
- if(flag < 3 && (f = fopen(cp,READ_TEXT)) != NULLFILE) {
- if((fgets(buf,sizeof(buf),f)) != 0) {
- number = atoi(buf);
- number++;
- }
- fclose(f);
- }
- if((sp = newsession("NNTP read",MORE,0,1)) != NULLSESSION) {
- for(;;) {
- if(number < 1)
- number = 1;
- sp->ttystate.echo = sp->ttystate.edit = 0;
- row = Nrows - 4;
- sprintf(cp,"%s/%d",art->path,number);
-
- if((f = fopen(cp,READ_TEXT)) != NULLFILE) {
- tprintf("Msg #%d\n",number);
- while(fgets(buf,sizeof(buf),f),!feof(f)) {
- tputs(buf);
- if(--row == 0){
- row = keywait("--More--",0);
- switch(row){
- case -1:
- case 'q':
- fclose(f);
- goto done;
- case '\n':
- case '\r':
- row = 2;
- break;
- default:
- row = Nrows - 3;
- }
- }
- }
- fclose(f);
- } else {
- number--;
- tputs("No more news");
- }
- done:
- row = keywait("\nRead next/previous? (n/p/q)",0);
- switch(row) {
- case -1:
- case 'q':
- goto done2;
- case 'p':
- flag = 3;
- if(--number < 1)
- goto done2;
- continue;
- default:
- number++;
- continue;
- }
- }
- done2:
- if(flag < 3) {
- sprintf(cp,"%s/news.rc",art->path);
- if((f = fopen(cp,WRITE_TEXT)) != NULLFILE) {
- sprintf(cp,"%d\n",number);
- fputs(cp,f);
- fclose(f);
- }
- }
- keywait(NULLCHAR,1);
- freesession(sp);
- }
- } else {
- tprintf("No such newsgroup %s\n",art->group);
- }
- xfree(art->path);
- xfree(art->group);
- xfree(art);
- return 0;
- }
-
- static int
- donnreply(int argc,char *argv[],void *p)
- {
- if(argc < 2 && Post.reply != NULLCHAR)
- tprintf("%s\n",Post.reply);
- else {
- xfree(Post.reply);
- Post.reply = strxdup(argv[1]);
- }
- return 0;
- }
-
- static int
- donnsig(int argc,char *argv[],void *p)
- {
- char buf[80];
-
- if(argc < 2 && Post.sig != NULLCHAR)
- tprintf("%s\n",Post.sig);
- else if(argc > 1) {
- sprintf(buf,"%s/%s",Signature,argv[1]);
- if(access(buf,0) == 0) {
- if(Post.sig != NULLCHAR)
- xfree(Post.sig);
- Post.sig = strxdup(buf);
- } else {
- tputs("No such signature file\n");
- return -1;
- }
- }
- return 0;
- }
-
- static int
- donnuser(int argc,char *argv[],void *p)
- {
- if(argc < 2 && Post.user != NULLCHAR)
- tprintf("%s\n",Post.user);
- else {
- xfree(Post.user);
- Post.user = strxdup(argv[1]);
- }
- return 0;
- }
-
-
- /****************************************************************/
- /* */
- /* This command will add a new newsgroup to the filesystem. */
- /* */
- /* Syntax: nntp create <newsgroup> */
- /* Example: nntp create ampr.news.nrn.sources */
- /* */
- /****************************************************************/
-
- static int
- donncreate(int argc, char *argv[], void *p)
- {
- FILE *f;
- char line[LineLen];
- int update_cntrl = 0;
-
- if ((f = open_file(Pointer,READ_TEXT,0,1)) == NULLFILE)
- return -1;
-
- for (;;) {
- if (fgets(line,LineLen,f) == NULL) {
- /* update pointerfile */
- update_cntrl = 1;
- break;
- }
- if (strcspn(line," ") != strlen(argv[1]))
- continue;
- if (strnicmp(argv[1],line,strlen(argv[1])) == 0)
- /* newsgroup in pointerfile exists */
- break;
- }
- fclose(f);
- /* creating path to this newsgroup */
- if (make_path(argv[1],update_cntrl))
- return -1;
-
- if ( (f=fopen(Active,APPEND_TEXT))==NULLFILE )
- return -1;
-
- for (;;) {
- if (fgets(line,LineLen,f) == NULL) {
- /* update active file */
- fprintf(f,"%s 00000 00001 y\n",argv[1]);
- break;
- }
- if (strcspn(line," ") != strlen(argv[1]))
- continue;
- if (strnicmp(argv[1],line,strlen(argv[1])) == 0)
- /* newsgroup in active file exists */
- break;
- }
- fclose(f);
- return 0;
- }
-
- /********************************************************************/
- /* */
- /* This command will control, how incoming articles are processed. */
- /* If fullauto flag is set, the nntp control files are updated to */
- /* include the new group and the subdirectories are automaticly */
- /* generated. Otherwise, all news that are not in the active file */
- /* will go to \spool\news\junk. */
- /* */
- /* Syntax: nntp config <yes|no> */
- /* Default: nntp config yes */
- /* */
- /********************************************************************/
-
- static int
- donnconfig(int argc,char *argv[],void *p)
- {
- return setbool(&fullauto,"NNTP AutoConfig",argc,argv);
- }
-
-
-
- #ifdef POST_ENBL
- /*************************************************************/
- /* */
- /* Set POST-Command enable/disable */
- /* */
- /* Syntax: nntp post <yes|no> */
- /* Default: nntp post yes */
- /* */
- /*************************************************************/
-
- static int
- dopostok(int argc,char *argv[],void *p)
- {
- return setbool(&postingok,"NNTP Posting",argc,argv);
- }
- #endif
-
-
- #ifdef NNTPLIFETIME
- /*************************************************************/
- /* */
- /* Set History Lifetime (unit: days) */
- /* */
- /* NEWNEWS-Polls with date/time older than lifetime */
- /* will not accepted. Incoming news are redirected to \JUNK */
- /* */
- /* Syntax: nntp lifetime <value> */
- /* Default: nntp lifetime 180 */
- /* */
- /*************************************************************/
-
- static int
- dolifetime(int argc,char *argv[],void *p)
- {
- return setintrc(&lifetime,"NNTP Lifetime",argc,argv,1,3650);
- }
-
- #endif
-
-
- #ifdef NNTPRESTRICT
- /*************************************************************/
- /* */
- /* Enable/Disable NNTP restriction in handling newnews */
- /* command without top level group specification */
- /* */
- /* Syntax: nntp restrict <yes|no> */
- /* Default: nntp restrict no */
- /* */
- /*************************************************************/
-
- static int
- dorestrict(int argc,char *argv[],void *p)
- {
- return setbool(&restrict,"NNTP Restriction",argc,argv);
- }
- #endif
-
-
- /* cmd parser */
- int
- donntp(int argc,char *argv[],void *p)
- {
- struct cmds Nntp[] = {
- "active", donnactive, 0, 0, NULLCHAR,
- "add", donnadds, 0, 3, "nntp add <hostid> <interval> [hh:mm-hh:mm] <groups>",
- "config", donnconfig, 0, 0, NULLCHAR,
- "create", donncreate, 0, 2, "nntp create <newsgroup>",
- "drop", donndrops, 0, 2, "nntp drop <newsserver>",
- "dump", donndump, 0, 3, "nntp dump <newsgroup> <mailfile>",
- "fullname", donnfull, 0, 0, NULLCHAR,
- "hostname", donnhost, 0, 0, NULLCHAR,
- "ihave", donnihave, 0, 0, NULLCHAR,
- "kick", donnkick, 0, 2, "nntp kick <newsserver>",
- #ifdef NNTPLIFETIME
- "lifetime", dolifetime, 0, 0, NULLCHAR,
- #endif
- "list", donnlists, 0, 0, NULLCHAR,
- #ifdef LZW
- "lzw", donnlzw, 0, 0, NULLCHAR,
- #endif
- "maxclient", donnmaxcli, 0, 0, NULLCHAR,
- "organ", donnorgan, 0, 0, NULLCHAR,
- "post", donnpost, 2048, 0, NULLCHAR,
- #ifdef POST_ENBL
- "postok", dopostok, 0, 0, NULLCHAR,
- #endif
- "quiet", donnquiet, 0, 0, NULLCHAR,
- "read", donnread, 1024, 2, "nntp read <newsgroup> [number]",
- "reply", donnreply, 0, 0, NULLCHAR,
- #ifdef NNTPRESTRICT
- "restrict", dorestrict, 0, 0, NULLCHAR,
- #endif
- "signature", donnsig, 0, 0, NULLCHAR,
- "user", donnuser, 0, 0, NULLCHAR,
- NULLCHAR,
- };
-
- return (subcmd(Nntp,argc,argv,p));
- }
-
-